// Windows/FileSystem.cpp

#include "StdAfx.h"

#include "FileSystem.h"
#include "Common/System/Defs.h"

namespace Common {
namespace FileSystem {

typedef BOOL (WINAPI * GetDiskFreeSpaceExPointer)(
  LPCTSTR lpDirectoryName,                 // directory name
  PULARGE_INTEGER lpFreeBytesAvailable,    // bytes available to caller
  PULARGE_INTEGER lpTotalNumberOfBytes,    // bytes on disk
  PULARGE_INTEGER lpTotalNumberOfFreeBytes // free bytes on disk
);

bool GetDiskFreeSpace(LPCTSTR rootPathName,
    UINT64 &clusterSize, UINT64 &totalSize, UINT64 &freeSize)
{
  GetDiskFreeSpaceExPointer pGetDiskFreeSpaceEx =
      (GetDiskFreeSpaceExPointer)GetProcAddress(
      GetModuleHandle(TEXT("kernel32.dll")), "GetDiskFreeSpaceExA");

  bool sizeIsDetected = false;
  if (pGetDiskFreeSpaceEx)
  {
    ULARGE_INTEGER i64FreeBytesToCaller, totalSize2, freeSize2;
    sizeIsDetected = BOOLToBool(pGetDiskFreeSpaceEx(rootPathName,
                &i64FreeBytesToCaller,
                &totalSize2,
                &freeSize2));
    totalSize = totalSize2.QuadPart;
    freeSize = freeSize2.QuadPart;
  }

  DWORD numSectorsPerCluster;
  DWORD bytesPerSector;
  DWORD numberOfFreeClusters;
  DWORD totalNumberOfClusters;

  if (!::GetDiskFreeSpace(rootPathName,
      &numSectorsPerCluster,
      &bytesPerSector,
      &numberOfFreeClusters,
      &totalNumberOfClusters))
    return false;

  clusterSize = (UINT64)bytesPerSector * (UINT64)numSectorsPerCluster;
  if (!sizeIsDetected)
  {
    totalSize =  clusterSize * (UINT64)totalNumberOfClusters;
    freeSize =  clusterSize * (UINT64)numberOfFreeClusters;
  }
  return true;
}


}}
